<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Sensors and Sensor Boards</title>
<meta name="author" content="David Gay, Philip Levis, Wei Hong, Joe Polastre, and Gilman Tolle" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009/02/03 23:07:32 $
:version: $Revision: 1.13 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="sensors-and-sensor-boards">
<h1 class="title">Sensors and Sensor Boards</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">109</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>David Gay, Philip Levis, Wei Hong, Joe Polastre, and Gilman Tolle</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>This memo documents how sensor drivers are organized in TinyOS and how
sets of sensor drivers are combined into sensor boards and sensor
platforms, along with general principles followed by the components
that provide access to sensors.</p>
</div>
<div class="section">
<h1><a id="principles" name="principles">1. Principles</a></h1>
<p>This section describes the basic organization principles for sensor
drivers in TinyOS.</p>
<p>For background, a sensor can be attached to the microcontroller on a
TinyOS platform through a few different types of connections:</p>
<blockquote>
<ul class="simple">
<li>Included within the microcontroller itself</li>
<li>Connected to general-purpose IO pins for level/edge detection</li>
<li>Connected to an ADC in the microcontroller for voltage sampling</li>
<li>Connected to general-purpose IO pins for digital communication</li>
<li>Connected through a standard digital bus protocol (1-Wire, I2C, SPI)</li>
</ul>
</blockquote>
<p>Physically, these connections can also be decoupled by attaching the
sensors to a <cite>sensor board</cite>, which can be removed from the TinyOS
platform, and could attach to multiple different TinyOS platforms.</p>
<p>The capabilities of a physical sensor are made available to a TinyOS
application through a <cite>sensor driver</cite>.</p>
<p>According to the HAA <a class="citation-reference" href="#tep2" id="id1" name="id1">[TEP2]</a>, TinyOS devices SHOULD provide both
simple hardware-independent interfaces for common-case use (HIL) and
rich hardware-dependent interfaces for special-case use (HAL). Sensor
drivers SHOULD follow this spirit as well.</p>
<p>TinyOS 2.x represents each sensor as an individual component. This
allows the compilation process to minimize the amount of code
included. A sensor board containing multiple sensors SHOULD be
represented as a collection of components, one for each sensor,
contained within a sensor board directory.</p>
<p>Sensors, being physical devices that can be shared, can benefit from
virtualization and arbitration. This document describes a design
pattern for sensor virtualization that SHOULD be followed by sensor
drivers.</p>
<p>The same physical sensor can be attached to multiple different TinyOS
platforms, through platform-dependent interconnections. The common
logic of sensor driver SHOULD be factored into chip-dependent,
platform-independent components, and those components SHOULD be bound
to the hardware resources on a platform by platform-dependent
components, and to the hardware resources on a sensor board by
sensorboard-dependent components.</p>
<p>A physical sensor has a general class and a specific set of
performance characteristics, captured by the make and model of the
sensor itself. The naming of the sensor driver components SHOULD
reflect the specifc name of the sensor, and MAY provide a component
with a generic name for application authors who only care about the
general class of the sensor.</p>
<p>This document requires that sensor components specify the range (in
bits) of values returned by sensor drivers, but takes no position on
the meaning of these values. They MAY be raw uninterpreted values or
they MAY have some physical meaning. If a driver returns uninterpreted
values, the driver MAY provide additional interfaces that would allow
higher-level clients to obtain information (e.g. calibration
coefficients) needed to properly interpret the value.</p>
</div>
<div class="section">
<h1><a id="sensor-hil-components" name="sensor-hil-components">2. Sensor HIL Components</a></h1>
<p>A sensor HIL component MUST provide:</p>
<ul class="simple">
<li>One or more SID interfaces <a class="citation-reference" href="#tep114" id="id2" name="id2">[TEP114]</a>, for reading data.</li>
</ul>
<p>A sensor HIL component MAY provide:</p>
<ul class="simple">
<li>One or more SID interfaces <a class="citation-reference" href="#tep114" id="id3" name="id3">[TEP114]</a>, for reading or
writing calibration coefficients or control registers.</li>
</ul>
<p>A sensor device driver SHOULD be a generic component that virtualizes
access to the sensor. A sensor device driver can provide such
virtualization for itself by defining a nesC generic client
component. When a client component is being used, a call to a
top-level SID interface SHOULD be delayed when the device is busy,
rather than failing. Using one of the system arbiters can make the
implementation of this requirement easier to accomplish.</p>
<p>For example:</p>
<pre class="literal-block">
generic configuration SensirionSht11C() {
  provides interface Read&lt;uint16_t&gt; as Temperature;
  provides interface ReadStream&lt;uint16_t&gt; as TemperatureStream;
  provides interface DeviceMetadata as TemperatureDeviceMetadata;

  provides interface Read&lt;uint16_t&gt; as Humidity;
  provides interface ReadStream&lt;uint16_t&gt; as HumidityStream;
  provides interface DeviceMetadata as HumidityDeviceMetadata;
}
implementation {
  // connect to the ADC HIL, GPIO HAL, or sensor's HAL
}
</pre>
<p>When a HIL component is being used, the sensor MUST initialize itself,
either by including the <cite>MainC</cite> component and wiring to the
<cite>SoftwareInit</cite> interface, or by allowing a lower-level component (like
an ADC) to initialize itself.</p>
<p>In addition, the HIL sensor driver MUST start the physical sensor
automatically. For sensors without a constant power draw, the sensor
MAY be started once at boot time by wiring to the <cite>MainC.Boot</cite>
interface. Sensors that draw appreciable power MUST be started in
response to a call to one of the top-level SID interfaces, and stopped
some time after that call completes. Using one of the power-management
components described in <a class="citation-reference" href="#tep115" id="id4" name="id4">[TEP115]</a> can make this implementation easier.</p>
<p>Generally, simple types are made up of octets. However, sensor values
often have levels of precision besides a multiple of 8. To account for
such cases, each device MUST specify the precision of each one of its
interfaces by providing the DeviceMetadata interface:</p>
<pre class="literal-block">
interface DeviceMetadata {
  command uint8_t getSignificantBits();
}
</pre>
<p>The name of the instance of DeviceMetadata MUST clearly indicate which
interface it corresponds to.</p>
<p>The getSignificantBits() call MUST return the number of significant
bits in the reading. For example, a sensor reading taken from a 12-bit
ADC would typically return the value 12 (it might return less if, e.g.,
physical constraints limit the maximum A/D result to 10-bits).</p>
<p>Sensor driver components SHOULD be named according to the make and
model of the sensing device being presented. Using specific names
gives the developer the option to bind to a particular sensor, which
provides compile-time detection of missing sensors. However, wrapper
components using &quot;common&quot; names MAY also be provided by the driver
author, to support application developers who are only concerned with
the particular type of the sensor and not its make, model, or detailed
performance characteristics.</p>
<p>A &quot;common&quot; naming layer atop a HIL might look like this:</p>
<pre class="literal-block">
generic configuration TemperatureC() {
  provides interface Read&lt;uint16_t&gt;;
  provides interface ReadStream&lt;uint16_t&gt;;
  provides interface DeviceMetadata;
}
implementation {
  components new SensirionSht11C();
  Read = SensirionSht11C.Temperature;
  ReadStream = SensirionSht11C.TemperatureStream;
  DeviceMetadata = SensirionSht11C.TemperatureDeviceMetadata;
}

generic configuration HumidityC() {
  provides interface Read&lt;uint16_t&gt;;
  provides interface ReadStream&lt;uint16_t&gt;;
  provides interface DeviceMetadata;
}
implementation {
  components new SensirionSht11C();
  Read = SensirionSht11C.Humidity;
  ReadStream = SensirionSht11C.HumidityStream;
  DeviceMetadata = SensirionSht11C.HumidityDeviceMetadata;
}
</pre>
</div>
<div class="section">
<h1><a id="sensor-hal-components" name="sensor-hal-components">3. Sensor HAL Components</a></h1>
<p>Sensors with a richer interface than would be supported by the SID
interfaces MAY provide a HAL component in addition to a HIL
component.</p>
<p>A sensor HAL component MUST provide:</p>
<ul class="simple">
<li>A SID-based interface or a specific hardware-dependent interface
with commands for sampling and controlling the sensor device.</li>
</ul>
<p>A sensor HAL component MAY need to provide:</p>
<ul class="simple">
<li>A <cite>StdControl</cite> or <cite>SplitControl</cite> interface for manual power
management by the user, following the conventions described in
<a class="citation-reference" href="#tep115" id="id5" name="id5">[TEP115]</a>.</li>
<li>A <cite>Resource</cite> interface for requesting access to the device and
possibly performing automated power management, following
the conventions described in <a class="citation-reference" href="#tep108" id="id6" name="id6">[TEP108]</a> and <a class="citation-reference" href="#tep115" id="id7" name="id7">[TEP115]</a>.</li>
<li>Any other interfaces needed to control the device, e.g., to
read or write calibration coefficients.</li>
</ul>
<p>For example:</p>
<pre class="literal-block">
configuration SensirionSht11DeviceC {
  provides interface Resource[ uint8_t client ];
  provides interface SensirionSht11[ uint8_t client ];
}
implementation {
  // connect to the sensor's platform-dependent HPL here
}
</pre>
</div>
<div class="section">
<h1><a id="sensor-component-organization-and-compiler-interaction-guidelines" name="sensor-component-organization-and-compiler-interaction-guidelines">4. Sensor Component Organization and Compiler Interaction Guidelines</a></h1>
<p>Sensors are associated either with a particular sensor board or with a
particular platform. Both sensors and sensor boards MUST have unique
names. Case is significant, but two sensor (or sensor board) names
MUST differ in more than case. This is necessary to support platforms
where filename case differences are not significant.</p>
<p>Each sensor board MUST have its own directory whose name is the sensor
board's unique name (referred to as &lt;sensorboard&gt; in the rest of this
section). Default TinyOS 2.x sensor boards are placed in
<tt class="docutils literal"><span class="pre">tos/sensorboards/&lt;sensorboard&gt;</span></tt>, but sensor board directories can be
placed anywhere as long as the nesC compiler receives a <tt class="docutils literal"><span class="pre">-I</span></tt> directive
pointing to the sensor board's directory. Each sensor board directory
MUST contain a <tt class="docutils literal"><span class="pre">.sensor</span></tt> file (described below). If the
sensor board wishes to define any C types or constants, it SHOULD
place these in a file named <tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;.h</span></tt> in the sensor board's
directory.</p>
<p>A sensor board MAY contain components that override the default TinyOS
<em>demo sensors</em>. This allows the sensor board to easily be used with
TinyOS sample applications that use the demo sensors. If a sensor
board wishes to override the default demo sensor:</p>
<ul>
<li><p class="first">It MUST provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> with the
following signature:</p>
<pre class="literal-block">
provides interface Read&lt;uint16_t&gt;;
provides interface DeviceMetadata;
</pre>
</li>
<li><p class="first">It MAY provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorNowC</span></tt> with the
following signature:</p>
<pre class="literal-block">
provides interface ReadNow&lt;uint16_t&gt;;
provides interface DeviceMetadata;
</pre>
<p>This component SHOULD sample the same sensor as <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt>.</p>
</li>
<li><p class="first">It MAY provide a generic component named <tt class="docutils literal"><span class="pre">DemoSensorStreamC</span></tt> with the
following signature:</p>
<pre class="literal-block">
provides interface ReadStream&lt;uint16_t&gt;;
provides interface DeviceMetadata;
</pre>
<p>This component SHOULD sample the same sensor as <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt>.</p>
</li>
</ul>
<p>These components MUST be an alias for one of the sensor board's usual
sensors, though they change the precision of the sensor if necessary.
For instance, if <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> is an alias for a 20-bit sensor that
provides a <tt class="docutils literal"><span class="pre">Read&lt;uint32_t&gt;</span></tt> interface, <tt class="docutils literal"><span class="pre">DemoSensorC</span></tt> would still
provide <tt class="docutils literal"><span class="pre">Read&lt;uint16_t&gt;</span></tt> and would include code to reduce the
precision of the aliased sensor.</p>
<div class="section">
<h2><a id="compiler-interaction" name="compiler-interaction">4.1 Compiler Interaction</a></h2>
<p>When the <tt class="docutils literal"><span class="pre">ncc</span></tt> nesC compiler frontend is passed a <tt class="docutils literal"><span class="pre">-board=X</span></tt> option,
it executes the <tt class="docutils literal"><span class="pre">.sensor</span></tt> file found in the sensor board directory
<tt class="docutils literal"><span class="pre">X</span></tt>.  This file is a perl script which can add or modify any
compile-time options necessary for the sensor board. It MAY modify the
following perl variables, and MUST NOT modify any others:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">&#64;includes</span></tt>: This array contains the TinyOS search path, i.e., the
directories which will be passed to nescc (the TinyOS-agnostic nesC
compiler) as <tt class="docutils literal"><span class="pre">-I</span></tt> arguments. You MUST add to <tt class="docutils literal"><span class="pre">&#64;includes</span></tt> any
directories needed to compile this sensor board's components.  For
instance, if your sensor boards depends on support code found in
<tt class="docutils literal"><span class="pre">tos/chips/sht11</span></tt>, you would add <tt class="docutils literal"><span class="pre">&quot;%T/chips/sht11&quot;</span></tt> to <tt class="docutils literal"><span class="pre">&#64;includes</span></tt>.</li>
<li><tt class="docutils literal"><span class="pre">&#64;new_args</span></tt>: This is the array of arguments which will be passed to
nescc. You MUST add any arguments other than <tt class="docutils literal"><span class="pre">-I</span></tt> that are necessary
to compile your sensor board components to <tt class="docutils literal"><span class="pre">&#64;new_args</span></tt>.</li>
</ul>
<p>If a sensor is associated with a platform <cite>P</cite> rather than a sensor
board, then that platform MUST ensure that, when compiling for
platform <cite>P</cite>, all directories needed to compile that sensor's
component are added to the TinyOS search path (see <a class="citation-reference" href="#tep131" id="id8" name="id8">[TEP131]</a> for
information on how to set up a TinyOS platform).</p>
</div>
<div class="section">
<h2><a id="sensor-components" name="sensor-components">4.2 Sensor Components</a></h2>
<p>A particular sensor is typically supported by many components,
including the HIL and HAL components from Sections 2 and 3, A/D
conversion components (for analog sensors), digital bus components
(e.g., SPI, for digital sensors), system services (timers, resource
and power management, ...), glue components (to connect sensors,
sensor boards and platforms), etc.  These components can be divided
into three classes: sensorboard-dependent, platform-dependent and
platform-independent. The sensorboard and platform MUST ensure
(Section 4.1) that all these components can be found at compile-time.</p>
<p>Because the same physical sensor can be used on many platforms or
sensor boards, and attached in many different ways, to maximize code
reuse the organization of sensor drivers SHOULD reflect the
distinction between sensor and sensor interconnect. The sensor
components SHOULD be platform-independent, while the sensor
interconnect components are typically sensorboard or
platform-dependent. However, some sensors (e.g. analong sensors) will
not have a sufficiently large amount of platform-independent logic to
justify creating platform-independent components.</p>
<p>The following guidelines specify how to organize sensor and sensor
interconnect components within TinyOS's directory hierarchy. These
guidelines are only relevant to components that are part of the core
source tree. The string <tt class="docutils literal"><span class="pre">&lt;sensor&gt;</span></tt> SHOULD reflect the make and model
of the sensor device.</p>
<ul class="simple">
<li>Platform-independent sensor components that exist as part of a
larger chip, like a MCU internal voltage sensor, SHOULD be placed in
a subdirectory of the chip's directory
<tt class="docutils literal"><span class="pre">tos/&lt;chip&gt;/sensors/&lt;sensor&gt;</span></tt>.</li>
<li>Other platform-independent sensor components SHOULD be placed
in <tt class="docutils literal"><span class="pre">tos/chips/&lt;sensor&gt;</span></tt>.</li>
<li>Sensorboard-dependent sensor and sensor interconnect components
SHOULD be placed either in the <tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;</span></tt> directory or in a
<tt class="docutils literal"><span class="pre">&lt;sensorboard&gt;/chips/&lt;sensor&gt;</span></tt> directory.</li>
<li>Platform-dependent sensor and sensor interconnect components SHOULD
be placed in <tt class="docutils literal"><span class="pre">tos/&lt;platform&gt;/chips/&lt;sensor&gt;</span></tt>.</li>
</ul>
</div>
</div>
<div class="section">
<h1><a id="authors-addresses" name="authors-addresses">5. Authors' Addresses</a></h1>
<div class="line-block">
<div class="line">David Gay</div>
<div class="line">2150 Shattuck Ave, Suite 1300</div>
<div class="line">Intel Research</div>
<div class="line">Berkeley, CA 94704</div>
<div class="line"><br /></div>
<div class="line">phone - +1 510 495 3055</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:david.e.gay&#64;intel.com">david.e.gay&#64;intel.com</a></div>
<div class="line"><br /></div>
<div class="line">Wei Hong</div>
<div class="line">Arch Rock</div>
<div class="line">657 Mission St. Suite 600</div>
<div class="line">San Francisco, CA 94105</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:wei.hong&#64;gmail.com">wei.hong&#64;gmail.com</a></div>
<div class="line"><br /></div>
<div class="line">Philip Levis</div>
<div class="line">358 Gates Hall</div>
<div class="line">Computer Science Department</div>
<div class="line">353 Serra Mall</div>
<div class="line">Stanford, CA 94305</div>
<div class="line"><br /></div>
<div class="line">phone - +1 650 725 9046</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:pal&#64;cs.stanford.edu">pal&#64;cs.stanford.edu</a></div>
<div class="line"><br /></div>
<div class="line">Joe Polastre</div>
<div class="line">467 Soda Hall</div>
<div class="line">UC Berkeley</div>
<div class="line">Berkeley, CA 94720</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:polastre&#64;cs.berkeley.edu">polastre&#64;cs.berkeley.edu</a></div>
<div class="line"><br /></div>
<div class="line">Gilman Tolle</div>
<div class="line">Arch Rock</div>
<div class="line">657 Mission St. Suite 600</div>
<div class="line">San Francisco, CA 94105</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:gtolle&#64;archrock.com">gtolle&#64;archrock.com</a></div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">6. Citations</a></h1>
<table class="docutils citation" frame="void" id="tep2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="tep2">[TEP2]</a></td><td>TEP 2: Hardware Abstraction Architecture</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep108" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id6" name="tep108">[TEP108]</a></td><td>TEP 108: Resource Arbitration</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep114" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="tep114">[TEP114]</a></td><td><em>(<a class="fn-backref" href="#id2">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> TEP 114: SIDs: Source and Sink Indepedent Drivers</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep115" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="tep115">[TEP115]</a></td><td><em>(<a class="fn-backref" href="#id4">1</a>, <a class="fn-backref" href="#id5">2</a>, <a class="fn-backref" href="#id7">3</a>)</em> TEP 115: Power Management of Non-Virtualized Devices</td></tr>
</tbody>
</table>
<table class="docutils citation" frame="void" id="tep131" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id8" name="tep131">[TEP131]</a></td><td>TEP 131: Creating a New Platform for TinyOS 2.x</td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="appendix-a-sensor-driver-examples" name="appendix-a-sensor-driver-examples">Appendix A: Sensor Driver Examples</a></h1>
<div class="section">
<h2><a id="analog-adc-connected-sensor" name="analog-adc-connected-sensor">1. Analog ADC-Connected Sensor</a></h2>
<p>The Analog sensor requires two components</p>
<ul class="simple">
<li>a component to present the sensor itself (HamamatsuS1087ParC)</li>
<li>a component to select the appropriate hardware resources, such as
ADC port 4, reference voltage 1.5V, and a slow sample and hold time
(HamamatsuS1087ParP).</li>
</ul>
<p>The AdcReadClientC component and underlying machinery handles all of
the arbitration and access to the ADC.</p>
<pre class="literal-block">
tos/platforms/telosa/chips/s1087/HamamatsuS1087ParC.nc

// HIL for the HamamatsuS1087 analog photodiode sensor
generic configuration HamamatsuS1087ParC() {
  provides interface Read&lt;uint16_t&gt;;
  provides interface ReadStream&lt;uint16_t&gt;;
  provides interface DeviceMetadata;
}
implementation {
  // Create a new A/D client and connect it to the Hamamatsu S1087 A/D
  // parameters
  components new AdcReadClientC();
  Read = AdcReadClientC;

  components new AdcReadStreamClientC();
  ReadStream = AdcReadStreamClientC;

  components HamamatsuS1087ParP;
  DeviceMetadata = HamamatsuS1087ParP;
  AdcReadClientC.AdcConfigure -&gt; HamamatsuS1087ParP;
  AdcReadStreamClientC.AdcConfigure -&gt; HamamatsuS1087ParP;
}
</pre>
<pre class="literal-block">
tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc

#include &quot;Msp430Adc12.h&quot;

// A/D parameters for the Hamamatsu - see the MSP430 A/D converter manual,
// Hamamatsu specification, Telos hardware schematic and TinyOS MSP430
// A/D converter component specifications for the explanation of these
// parameters
module HamamatsuS1087ParP {
  provides interface AdcConfigure&lt;const msp430adc12_channel_config_t*&gt;;
  provides interface DeviceMetadata;
}
implementation {
  msp430adc12_channel_config_t config = {
    inch: INPUT_CHANNEL_A4,
    sref: REFERENCE_VREFplus_AVss,
    ref2_5v: REFVOLT_LEVEL_1_5,
    adc12ssel: SHT_SOURCE_ACLK,
    adc12div: SHT_CLOCK_DIV_1,
    sht: SAMPLE_HOLD_4_CYCLES,
    sampcon_ssel: SAMPCON_SOURCE_SMCLK,
    sampcon_id: SAMPCON_CLOCK_DIV_1
  };

  async command const msp430adc12_channel_config_t* AdcConfigure.getConfiguration() {
    return &amp;config;
  }

  command uint8_t DeviceMetadata.getSignificantBits() { return 12; }
}
</pre>
</div>
<div class="section">
<h2><a id="binary-pin-connected-sensor" name="binary-pin-connected-sensor">2. Binary Pin-Connected Sensor</a></h2>
<p>The Binary sensor gets a bit more complex, because it has three
components:</p>
<ul class="simple">
<li>one to present the sensor (UserButtonC)</li>
<li>one to execute the driver logic (UserButtonLogicP)</li>
<li>one to select the appropriate hardware resources, such as MSP430
Port 27 (HplUserButtonC).</li>
</ul>
<p>Note that the presentation of this sensor is not arbitrated because
none of the operations are split-phase.</p>
<pre class="literal-block">
tos/platforms/telosa/UserButtonC.nc

// HIL for the user button sensor on Telos-family motes
configuration UserButtonC {
  provides interface Get&lt;bool&gt;; // Get button status
  provides interface Notify&lt;bool&gt;; // Get button-press notifications
  provides interface DeviceMetadata;
}
implementation {

  // Simply connect the button logic to the button HPL
  components UserButtonLogicP;
  Get = UserButtonLogicP;
  Notify = UserButtonLogicP;
  DeviceMetadata = UserButtonLogicP;

  components HplUserButtonC;
  UserButtonLogicP.GpioInterrupt -&gt; HplUserButtonC.GpioInterrupt;
  UserButtonLogicP.GeneralIO -&gt; HplUserButtonC.GeneralIO;
}
</pre>
<pre class="literal-block">
tos/platforms/telosa/UserButtonLogicP.nc

// Transform the low-level (GeneralIO and GpioInterrupt) interface to the
// button to high-level SID interfaces
module UserButtonLogicP {
  provides interface Get&lt;bool&gt;;
  provides interface Notify&lt;bool&gt;;
  provides interface DeviceMetadata;

  uses interface GeneralIO;
  uses interface GpioInterrupt;
}
implementation {
  norace bool m_pinHigh;

  task void sendEvent();

  command bool Get.get() { return call GeneralIO.get(); }

  command error_t Notify.enable() {
    call GeneralIO.makeInput();

    // If the pin is high, we need to trigger on falling edge interrupt, and
    // vice-versa
    if ( call GeneralIO.get() ) {
      m_pinHigh = TRUE;
      return call GpioInterrupt.enableFallingEdge();
    } else {
      m_pinHigh = FALSE;
      return call GpioInterrupt.enableRisingEdge();
    }
  }

  command error_t Notify.disable() {
    return call GpioInterrupt.disable();
  }

  // Button changed, signal user (in a task) and update interrupt detection
  async event void GpioInterrupt.fired() {
    call GpioInterrupt.disable();

    m_pinHigh = !m_pinHigh;

    post sendEvent();
  }

  task void sendEvent() {
    bool pinHigh;
    pinHigh = m_pinHigh;

    signal Notify.notify( pinHigh );

    if ( pinHigh ) {
      call GpioInterrupt.enableFallingEdge();
    } else {
      call GpioInterrupt.enableRisingEdge();
    }
  }

  command uint8_t DeviceMetadata.getSignificantBits() { return 1; }
}
</pre>
<pre class="literal-block">
tos/platforms/telosa/HplUserButtonC.nc

// HPL for the user button sensor on Telos-family motes - just provides
// access to the I/O and interrupt control for the pin to which the
// button is connected
configuration HplUserButtonC {
  provides interface GeneralIO;
  provides interface GpioInterrupt;
}
implementation {

  components HplMsp430GeneralIOC as GeneralIOC;

  components new Msp430GpioC() as UserButtonC;
  UserButtonC -&gt; GeneralIOC.Port27;
  GeneralIO = UserButtonC;

  components HplMsp430InterruptC as InterruptC;

  components new Msp430InterruptC() as InterruptUserButtonC;
  InterruptUserButtonC.HplInterrupt -&gt; InterruptC.Port27;
  GpioInterrupt = InterruptUserButtonC.Interrupt;
}
</pre>
</div>
<div class="section">
<h2><a id="digital-bus-connected-sensor" name="digital-bus-connected-sensor">3. Digital Bus-Connected Sensor</a></h2>
<p>The Digital sensor is the most complex out of the set, and includes
six components:</p>
<ul class="simple">
<li>one to present the sensor (SensirionSht11C)</li>
<li>one to request arbitrated access and to transform the sensor HAL
into the sensor HIL (SensirionSht11P)</li>
<li>one to present the sensor HAL (HalSensirionSht11C)</li>
<li>one to perform the driver logic needed to support the HAL, which
twiddles pins according to a sensor-specific protocol
(SensirionSht11LogicP).</li>
<li>one to select the appropriate hardware resources, such as the clock,
data, and power pins, and to provide an arbiter for the sensor
(HplSensirionSht11C).</li>
<li>one to perform the power control logic needed to support the power
manager associated with the arbiter (HplSensirionSht11P).</li>
</ul>
<p>This bus-connected sensor is overly complex because it does not rely
on a shared framework of bus manipulation components. A sensor built
on top of the I2C or SPI bus would likely require fewer components.</p>
<pre class="literal-block">
tos/platforms/telosa/chips/sht11/SensirionSht11C.nc

// HIL interface to Sensirion SHT11 temperature and humidity sensor
generic configuration SensirionSht11C() {
  provides interface Read&lt;uint16_t&gt; as Temperature;
  provides interface DeviceMetadata as TemperatureDeviceMetadata;
  provides interface Read&lt;uint16_t&gt; as Humidity;
  provides interface DeviceMetadata as HumidityDeviceMetadata;
}
implementation {
  // Instantiate the module providing the HIL interfaces
  components new SensirionSht11ReaderP();

  Temperature = SensirionSht11ReaderP.Temperature;
  TemperatureDeviceMetadata = SensirionSht11ReaderP.TemperatureDeviceMetadata;
  Humidity = SensirionSht11ReaderP.Humidity;
  HumidityDeviceMetadata = SensirionSht11ReaderP.HumidityDeviceMetadata;

  // And connect it to the HAL component for the Sensirion SHT11
  components HalSensirionSht11C;

  enum { TEMP_KEY = unique(&quot;Sht11.Resource&quot;) };
  enum { HUM_KEY = unique(&quot;Sht11.Resource&quot;) };

  SensirionSht11ReaderP.TempResource -&gt; HalSensirionSht11C.Resource[ TEMP_KEY ];
  SensirionSht11ReaderP.Sht11Temp -&gt; HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
  SensirionSht11ReaderP.HumResource -&gt; HalSensirionSht11C.Resource[ HUM_KEY ];
  SensirionSht11ReaderP.Sht11Hum -&gt; HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
}
</pre>
<pre class="literal-block">
tos/chips/sht11/SensirionSht11ReaderP.nc

// Convert Sensirion SHT11 HAL to HIL interfaces for a single
// client, performing automatic resource arbitration
generic module SensirionSht11ReaderP() {
  provides interface Read&lt;uint16_t&gt; as Temperature;
  provides interface DeviceMetadata as TemperatureDeviceMetadata;
  provides interface Read&lt;uint16_t&gt; as Humidity;
  provides interface DeviceMetadata as HumidityDeviceMetadata;

  // Using separate resource interfaces for temperature and humidity allows
  // temperature and humidity measurements to be requested simultaneously
  // (if a single Resource interface was used, a request for temperature would
  // prevent any humidity requests until the temperature measurement was complete)
  uses interface Resource as TempResource;
  uses interface Resource as HumResource;
  uses interface SensirionSht11 as Sht11Temp;
  uses interface SensirionSht11 as Sht11Hum;
}
implementation {
  command error_t Temperature.read() {
    // Start by requesting access to the SHT11
    return call TempResource.request();
  }

  event void TempResource.granted() {
    error_t result;
    // If the HAL measurement fails, release the SHT11 and signal failure
    if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
      call TempResource.release();
      signal Temperature.readDone( result, 0 );
    }
  }

  event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
    // Release the SHT11 and signal the result
    call TempResource.release();
    signal Temperature.readDone( result, val );
  }

  command uint8_t TemperatureDeviceMetadata.getSignificantBits() { return 14; }

  command error_t Humidity.read() {
    // Start by requesting access to the SHT11
    return call HumResource.request();
  }

  event void HumResource.granted() {
    error_t result;
    // If the HAL measurement fails, release the SHT11 and signal failure
    if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
      call HumResource.release();
      signal Humidity.readDone( result, 0 );
    }
  }

  event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
    // Release the SHT11 and signal the result
    call HumResource.release();
    signal Humidity.readDone( result, val );
  }

  command uint8_t HumidityDeviceMetadata.getSignificantBits() { return 12; }

  // Dummy handlers for unused portions of the HAL interface
  event void Sht11Temp.resetDone( error_t result ) { }
  event void Sht11Temp.measureHumidityDone( error_t result, uint16_t val ) { }
  event void Sht11Temp.readStatusRegDone( error_t result, uint8_t val ) { }
  event void Sht11Temp.writeStatusRegDone( error_t result ) { }

  event void Sht11Hum.resetDone( error_t result ) { }
  event void Sht11Hum.measureTemperatureDone( error_t result, uint16_t val ) { }
  event void Sht11Hum.readStatusRegDone( error_t result, uint8_t val ) { }
  event void Sht11Hum.writeStatusRegDone( error_t result ) { }

  // We need default handlers as a client may wire to only the Temperature
  // sensor or only the Humidity sensor
  default event void Temperature.readDone( error_t result, uint16_t val ) { }
  default event void Humidity.readDone( error_t result, uint16_t val ) { }
}
</pre>
<pre class="literal-block">
tos/platforms/telosa/chips/sht11/HalSensirionSht11C.nc

// HAL interface to Sensirion SHT11 temperature and humidity sensor
configuration HalSensirionSht11C {
  // The SHT11 HAL uses resource arbitration to allow the sensor to shared
  // between multiple clients and for automatic power management (the SHT11
  // is switched off when no clients are waiting to use it)
  provides interface Resource[ uint8_t client ];
  provides interface SensirionSht11[ uint8_t client ];
}
implementation {
  // The HAL implementation logic
  components new SensirionSht11LogicP();
  SensirionSht11 = SensirionSht11LogicP;

  // And it's wiring to the SHT11 HPL - the actual resource management is
  // provided at the HPL layer
  components HplSensirionSht11C;
  Resource = HplSensirionSht11C.Resource;
  SensirionSht11LogicP.DATA -&gt; HplSensirionSht11C.DATA;
  SensirionSht11LogicP.CLOCK -&gt; HplSensirionSht11C.SCK;
  SensirionSht11LogicP.InterruptDATA -&gt; HplSensirionSht11C.InterruptDATA;

  components new TimerMilliC();
  SensirionSht11LogicP.Timer -&gt; TimerMilliC;

  components LedsC;
  SensirionSht11LogicP.Leds -&gt; LedsC;
}
</pre>
<pre class="literal-block">
tos/chips/sht11/SensirionSht11LogicP.nc

generic module SensirionSht11LogicP() {
  provides interface SensirionSht11[ uint8_t client ];

  uses interface GeneralIO as DATA;
  uses interface GeneralIO as CLOCK;
  uses interface GpioInterrupt as InterruptDATA;

  uses interface Timer&lt;TMilli&gt;;

  uses interface Leds;
}
implementation {

  ... bus protocol details omitted for brevity ...

}
</pre>
<pre class="literal-block">
tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc

// Low-level, platform-specific glue-code to access the SHT11 sensor found
// on telos-family motes - here  the HPL just provides resource management
// and access to the SHT11 data, clock and interrupt pins
configuration HplSensirionSht11C {
  provides interface Resource[ uint8_t id ];
  provides interface GeneralIO as DATA;
  provides interface GeneralIO as SCK;
  provides interface GpioInterrupt as InterruptDATA;
}
implementation {
  // Pins used to access the SHT11
  components HplMsp430GeneralIOC;

  components new Msp430GpioC() as DATAM;
  DATAM -&gt; HplMsp430GeneralIOC.Port15;
  DATA = DATAM;

  components new Msp430GpioC() as SCKM;
  SCKM -&gt; HplMsp430GeneralIOC.Port16;
  SCK = SCKM;

  components new Msp430GpioC() as PWRM;
  PWRM -&gt; HplMsp430GeneralIOC.Port17;

  // HPL logic for switching the SHT11 on and off
  components HplSensirionSht11P;
  HplSensirionSht11P.PWR -&gt; PWRM;
  HplSensirionSht11P.DATA -&gt; DATAM;
  HplSensirionSht11P.SCK -&gt; SCKM;

  components new TimerMilliC();
  HplSensirionSht11P.Timer -&gt; TimerMilliC;

  components HplMsp430InterruptC;
  components new Msp430InterruptC() as InterruptDATAC;
  InterruptDATAC.HplInterrupt -&gt; HplMsp430InterruptC.Port15;
  InterruptDATA = InterruptDATAC.Interrupt;

  // The arbiter and power manager for the SHT11
  components new FcfsArbiterC( &quot;Sht11.Resource&quot; ) as Arbiter;
  Resource = Arbiter;

  components new SplitControlPowerManagerC();
  SplitControlPowerManagerC.SplitControl -&gt; HplSensirionSht11P;
  SplitControlPowerManagerC.ArbiterInit -&gt; Arbiter.Init;
  SplitControlPowerManagerC.ArbiterInfo -&gt; Arbiter.ArbiterInfo;
  SplitControlPowerManagerC.ResourceDefaultOwner -&gt; Arbiter.ResourceDefaultOwner;
}
</pre>
<pre class="literal-block">
tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc

// Switch the SHT11 on and off, and handle the 11ms warmup delay
module HplSensirionSht11P {
  // The SplitControl interface powers the SHT11 on or off (it's automatically
  // called by the SHT11 power manager, see HplSensirionSht11C)
  // We use a SplitControl interface as we need to wait 11ms for the sensor to
  // warm up
  provides interface SplitControl;
  uses interface Timer&lt;TMilli&gt;;
  uses interface GeneralIO as PWR;
  uses interface GeneralIO as DATA;
  uses interface GeneralIO as SCK;
}
implementation {
  task void stopTask();

  command error_t SplitControl.start() {
    // Power SHT11 on and wait for 11ms
    call PWR.makeOutput();
    call PWR.set();
    call Timer.startOneShot( 11 );
    return SUCCESS;
  }

  event void Timer.fired() {
    signal SplitControl.startDone( SUCCESS );
  }

  command error_t SplitControl.stop() {
    // Power the SHT11 off
    call SCK.makeInput();
    call SCK.clr();
    call DATA.makeInput();
    call DATA.clr();
    call PWR.clr();
    post stopTask();
    return SUCCESS;
  }

  task void stopTask() {
    signal SplitControl.stopDone( SUCCESS );
  }
}
</pre>
</div>
<div class="section">
<h2><a id="mda100-sensor-board-directory-organization" name="mda100-sensor-board-directory-organization">4. MDA100 Sensor Board Directory Organization</a></h2>
<p>Here we show the organization of the sensor board directory for the
mica-family Xbow MDA100CA and MDA100CB sensor boards, which have
temperature and light sensors. It is found in
<tt class="docutils literal"><span class="pre">tos/sensorboards/mda100</span></tt>:</p>
<pre class="literal-block">
./tos/sensorboards/mda100:
.sensor                                       # Compiler configuration
ArbitratedPhotoDeviceP.nc                     # Light sensor support component
ArbitratedTempDeviceP.nc                      # Temperature sensor support component
DemoSensorC.nc                                # Override TinyOS's default sensor
PhotoC.nc                                     # Light sensor HIL
PhotoImplP.nc                                 # Light sensor support component
PhotoTempConfigC.nc                           # Shared support component
PhotoTempConfigP.nc                           # Shared support component
SharedAnalogDeviceC.nc                        # Shared support component
SharedAnalogDeviceP.nc                        # Shared support component
TempC.nc                                      # Temperature Sensor HIL
ca/TempImplP.nc                               # Temperature sensor support component
                                              # (MDA100CA board)
cb/TempImplP.nc                               # Temperature sensor support component
                                              # (MDA100CB board)
mda100.h                                      # Header file for mda100
</pre>
<p>This sensor board provides only a HIL (PhotoC and TempC components), and overrides the
TinyOS demo sensor (DemoSensorC). The demo sensor is an alias for PhotoC.</p>
<p>The two forms of the mda100 differ only by the wiring of the
temperature sensor.  The user has to specify which form of the sensor
board is in use by providing a <tt class="docutils literal"><span class="pre">-I%T/sensorboards/mda100/ca</span></tt> or
<tt class="docutils literal"><span class="pre">-I%T/sensorboards/mda100/cb</span></tt> compiler option.</p>
<p>This sensor board relies on a platform-provided <tt class="docutils literal"><span class="pre">MicaBusC</span></tt> component
that specifies how the mica-family sensor board bus is connected to
the microcontroller.</p>
</div>
</div>
</div>
</body>
</html>
